#include <iostream>
#include <unistd.h>
#include <pthread.h>
#include <vector>
using namespace std;

int cnt = 0;

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

void* Count(void * args)
{
    pthread_detach(pthread_self());

    uint64_t number = (uint64_t)args;
    cout << "pthread_t: " << number << " create success" << endl;
    while(true)
    {
        //多线程打印，显示器文件临界资源，下面有可能会发生消息错乱，上锁即可
        pthread_mutex_lock(&mutex);
        //我们怎么知道要让一个线程去休眠了？一定是临界资源不就绪，临界资源也有状态！
        //如何知道临界资源是否就绪?当然是我们判断出来的，那么判断是在访问临界资源?当然那是的，也就是判断必须在加锁之后！！！
        pthread_cond_wait(&cond, &mutex); //pthead_cond_wait 让线程等待的时候，会自动释放锁。
        cout << "pthread: " << number << ", cnt: " << cnt++ << endl;
        pthread_mutex_unlock(&mutex);
    }
}


int main()
{
    for(uint64_t i = 0; i < 5; i++)
    {
        pthread_t tid;
        //注意这里的第四个参数中，i不能直接传入它的地址，不然的话新线程和它用的就是同一个变量。一旦主线程将这个i改变了，那么新线程的这个i也就随之改变了
        //而在以前的代码是避免了直接传入i的地址的，而是通过new一个对象，传入对象的地址来规避这个问题的。
        //这里我们就是想要将i拷贝式的传入进去
        pthread_create(&tid, nullptr, Count, (void*)i);
        usleep(1000);
    }    
    sleep(3);
    cout << "main thread ctrl begin: " << endl;

    while(true) 
    {
        sleep(1);
        pthread_cond_signal(&cond); //唤醒在cond的等待队列的一个线程，默认都是第一个
        //pthread_cond_broadcast(&cond); //唤醒在cond的等待队列的所有线程。
        cout << "signal one thread ... " << endl;
    }
    return 0;
}



// void* getTicket(void* args)
// {
//     threadData *td = static_cast<threadData*>(args);
    
//     const char* name = td->_threadname.c_str();
//     while(true)
//     {
//         //pthread_mutex_lock(td->_lock); //申请锁成功，才能往后执行，不成功，阻塞等待
//         pthread_mutex_lock(&lock); //申请锁成功，才能往后执行，不成功，阻塞等待
//         if(tickets > 0)
//         {
//             usleep(1000);
//             printf("who = %s, get a ticket: %d\n", name, tickets);
//             tickets--;
//             pthread_mutex_unlock(&lock);
//             //pthread_mutex_unlock(td->_lock);
//         }
//         else
//         {
//             pthread_mutex_unlock(&lock);
//             // pthread_mutex_unlock(td->_lock);
//             break;
//         }
//         usleep(13); //有可能它一释放锁，就立马抢到了
//     }
//     printf("%s ... quit\n", name);
//     return nullptr;
// }